
module ResultProcess
        ( SimpleResult (..)
        , ResultProcessor (..)
        )
        where

import Data.Packed.Vector
import Numeric.GSL.Statistics

class ResultProcessor m where
        rprocess :: [Maybe Double]->m


data SimpleResult = SimpleResult {
        srMean          :: Double,
        srStd           :: Double,
        srSkew          :: Double,
        srKurtosis      :: Double,
        srSharpe        :: Double,
        srWins          :: Int,
        srLoss          :: Int,
        srAvgWin        :: Double,
        srAvgLoss       :: Double
        } deriving (Show)

instance ResultProcessor SimpleResult where
        rprocess xs = SimpleResult {
                srMean          = dm,
                srStd           = ds,
                srSkew          = dskew,
                srKurtosis      = dkurtosis,
                srSharpe        = dm/ds,
                srWins          = w,
                srLoss          = l,
                srAvgWin        = (mean . fromList) ws,
                srAvgLoss       = (mean . fromList) ls
                }
                where   dxs             = toVector xs
                        dm              = mean dxs
                        ds              = stddev dxs
                        dskew           = skew_m_sd dm ds dxs
                        dkurtosis       = kurtosis_m_sd dm ds dxs
                        (w, l, ws, ls)  = winsLosses xs 

winsLosses :: [Maybe Double] -> (Int, Int, [Double], [Double])
winsLosses = foldl summator (0, 0, [], [])
        where   summator (w, l, ws, ls) Nothing = (w, l, ws, ls)
                summator (w, l, ws, ls) (Just x)
                        | x > 0.0               = (w+1, l, x:ws, ls)
                        | x < 0.0               = (w, l+1, ws, x:ls)
                        | otherwise             = (w, l, ws, ls)

toVector :: [Maybe Double] -> Vector Double
toVector = fromList . toDouble

toDouble :: [Maybe Double] -> [Double]
toDouble (Nothing:xs) = toDouble xs
toDouble ((Just x):xs) = x:(toDouble xs)
toDouble []     = []
